

#include <config.h>
#include <klib.h>

#ifndef __GDT_H
#  define __GDT_H

#  ifdef CONF_SYS_AMD64

struct __GDT {

  uint16 limit;
  uint64 base;

} __attribute__ ((packed));

typedef struct __gdt GDT;

struct __GDT_entry {

  uint32   low_ignored;
  unit8    mid_low_ignored;
  unsigned ign1 : 2;
  unsigned conf : 1;
  unsigned data_code : 2;
  unsigned dpl : 2;
  unsigned present : 1;
  uint8    low_flags;
  uint8    high_flags;
  uint8    high_ignored;

} __attribute__ ((packed));

typedef struct __GDT_entry GDT_entry;

#  define GDT_FLAG_D    0x10
#  define GDT_FLAG_LONG 0x20
#  define GDT_CODE_SEG  3     // 11b
#  define GDT_DATA_SEG  2     // 10b

#  define CODE_SEG(entry) entry.data_code = GDT_CODE_SEG;
#  define DATA_SEG(entry) entry.data_code = GDT_DATA_SEG;

#  endif

#  ifdef CONF_SYS_I386

struct __GDT {

  uint16 limit;
  uint32 base;

} __attribute__((packed));

typedef struct __GDT GDT;

struct __GDT_entry {

  uint16   limit_low;
  uint16   base_low;
  uint8    base_mid;  
  unsigned type : 4;
  unsigned flags_low : 4;
  unsigned limit_high : 4;
  unsigned flags_high : 4;
  uint8    base_high;

} __attribute__((packed));

typedef struct __GDT_entry GDT_entry;

#    define SEG_FLAG_TYPE 0x01
#    define SEG_DPL_SYS   0x00
#    define SEG_DPL_USR   0x06
#    define SEG_PRESENT   0x08
#    define SEG_OP_SIZE   0x40
#    define SEG_GRAN      0x80

void _gdt_make_entry(GDT_entry *, uint32, uint32, uint8);

#    define CODE_SEG(entry) entry->type |= 10
#    define DATA_SEG(entry) entry->type |= 2

#  endif

void _flush_gdt();
void _build_gdt();
void gdt_init();

#endif
